package charts.legend
{
	import com.yahoo.astra.fl.utils.UIComponentUtil;
	
	import mx.core.UIComponent;
	
	import flash.display.DisplayObject;
	import flash.geom.Rectangle;

	//--------------------------------------
	//  Styles
	//--------------------------------------
	
	/**
     * The padding that separates the border of the component from its contents,
     * in pixels.
     *
     * @default 6
     */
    [Style(name="contentPadding", type="Number")]
	
	/**
     * The spacing that separates the each legend item.
     *
     * @default 6
     */
    [Style(name="gap", type="Number")]
	
	/**
     * The DisplayObject subclass used to display the background.
     */
    [Style(name="backgroundSkin", type="Class")]
	
	/**
	 * Provides a visual reference for the series in a Chart component.
	 * 
	 * @see com.yahoo.astra.fl.charts.Chart
	 * @see com.yahoo.astra.fl.charts.legend.LegendItem
	 * 
	 * @author Ivan Gong
	 */
	public class Legend extends UIComponent implements ILegend
	{	
		
	//--------------------------------------
	//  Static Variables
	//--------------------------------------
	
		/**
		 * @private
		 */
		private static var defaultStyles:Object = 
		{
			backgroundSkin: "ChartLegendBackground",
			contentPadding: 6,
			direction: "vertical",
			gap: 6
		};
		
		/**
		 * @private
		 * Styles to pass to the LegendItems
		 */
		private static const ITEM_STYLES:Object =
		{
			textFormat: "textFormat"
		};
		
	//--------------------------------------
	//  Static Methods
	//--------------------------------------
	
		/**
		 * @private
		 * @copy fl.core.UIComponent#getStyleDefinition()
		 */
		public static function getStyleDefinition():Object
		{
			return defaultStyles;
		}
		
	//--------------------------------------
	//  Constructor
	//--------------------------------------
	
		/**
		 * Constructor.
		 */
		public function Legend()
		{
			super();
		}
		
	//--------------------------------------
	//  Properties
	//--------------------------------------
	
		/**
		 * @private
		 * The background skin.
		 */
		protected var background:DisplayObject;
	
		/**
		 * @private
		 * The legend items displayed in this Legend.
		 */
		protected var legendItems:Array = [];
		
		/**
		 * @private
		 * Caches LegendItems for reuse when redrawing the Legend.
		 */
		private var _legendItemCache:Array;
		
		/**
		 * @private
		 * Storage for the dataProvider property.
		 */
		private var _dataProvider:Array = [];
		
		/**
		 * @inheritDoc
		 */
		public function get dataProvider():Array
		{
			return this._dataProvider;
		}
		
		/**
		 * @private
		 */
		public function set dataProvider(value:Array):void
		{
			this._dataProvider = value;
		}
		
	//--------------------------------------
	//  Protected Methods
	//--------------------------------------
		
		/**
		 * @private
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth,unscaledHeight);
			var dataInvalid:Boolean = true;
			var stylesInvalid:Boolean = true;
			
			if(stylesInvalid)
			{
				if(this.background)
				{
					this.removeChild(this.background);
					this.background = null;
				}
				var skinClass:Object = this.getStyle("backgroundSkin");
				this.background = UIComponentUtil.getDisplayObjectInstance(this, skinClass);
				this.addChildAt(this.background, 0);
			}
			
			if(dataInvalid && this.dataProvider)
			{
				this.createCache();
				this.updateLegendItems();
				this.clearCache();
			}
			
			this.layoutItems();
			
			if(this.background)
			{
				
				if(this.background is UIComponent)
				{
					this.background.width = this.width;
					this.background.height = this.height;
				}
			}
		}
		
		/**
		 * @private
		 * Loops through the data provider and displays a LegendItem
		 * for each item.
		 */
		protected function updateLegendItems():void
		{
			var itemCount:int = this.dataProvider.length;
			for(var i:int = 0; i < itemCount; i++)
			{
				var legendItem:LegendItem = this.getItem();
				legendItem.data = LegendItemData(dataProvider[i]);
				//this.copyStylesToChild(legendItem, ITEM_STYLES);
				//legendItem.drawNow();
				this.legendItems.push(legendItem);
			}
		}
		
		/**
		 * @private
		 * Standard renderer caching system.
		 */
		protected function createCache():void
		{
			this._legendItemCache = this.legendItems.concat();
			this.legendItems = [];
		}
		
		/**
		 * @private
		 * Either returns an old renderer from the cache or creates a new one.
		 */
		protected function getItem():LegendItem
		{
			if(this._legendItemCache.length > 0)
			{
				return this._legendItemCache.shift() as LegendItem;
			}
			var legendItem:LegendItem = new LegendItem();
			this.addChild(legendItem);
			return legendItem;
		}
		
		/**
		 * @private
		 * Clears any unused renderers from the cache.
		 */
		protected function clearCache():void
		{
			var cacheLength:int = this._legendItemCache.length;
			for(var i:int = 0; i < cacheLength; i++)
			{
				var legendItem:LegendItem = this._legendItemCache.pop() as LegendItem;
				this.removeChild(legendItem);
			}
		}
		
		/**
		 * @private
		 * Positions the LegendItems.
		 */
		protected function layoutItems():void
		{
			var oldWidth:Number = this.width;
			var oldHeight:Number = this.height;
			
			var contentPadding:Number = this.getStyle("contentPadding") as Number;
			var direction:String = this.getStyle("direction") as String;
			var gap:Number = this.getStyle("gap") as Number;
		
			/* var layout:BoxLayout = new BoxLayout();
			layout.verticalGap = layout.horizontalGap = gap;
			layout.direction = direction;
			if(this.background)
			{
				layout.addClient(this.background, {includeInLayout: false});
			}
			layout.paddingTop = layout.paddingRight = layout.paddingBottom = layout.paddingLeft = contentPadding
			var bounds:Rectangle = layout.layoutChildren(this, new Rectangle(0, 0, this.width, this.height));
			
			this.width = bounds.width;
			this.height = bounds.height;
			
			//if the size has changed, dispatch a resize event
			if(this.width != oldWidth || this.height != oldHeight)
			{
				this.dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE));
			} */
		}
	}
	
}
